// 读写锁 -> if 所有进程都是读操作，那么读是并行的（但是使用互斥锁，读操作也是串行的）
// 类型：pthread_rwlock_t

/*
question:
    8个线程操作同一个全局变量
    3个线程不定时写同一全局资源
    5个线程不定时读同一全局资源
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#define MAX 50

// 全局变量
int number = 0;

// 定义读写锁
pthread_rwlock_t rwlock;

// 写的线程的处理函数
void* writeNum(void* arg)
{
    for(int i = 0; i < MAX; ++i)
    {
        pthread_rwlock_wrlock(&rwlock);
        int cur = number;
        cur ++;
        number = cur;
        printf("write OP, number : %d, tid = %ld\n", number, pthread_self());
        pthread_rwlock_unlock(&rwlock);
        // 添加sleep目的是要看到多个线程交替工作
        usleep(rand() % 100);
    }

    return NULL;
}

// 读线程的处理函数
// 多个线程可以如果处理动作相同, 可以使用相同的处理函数
// 每个线程中的栈资源是独享
void* readNum(void* arg)
{
    for(int i = 0; i < MAX; ++i)
    {
        pthread_rwlock_rdlock(&rwlock);
        printf("read OP, number = %d, tid = %ld\n", number, pthread_self());
        pthread_rwlock_unlock(&rwlock);
        usleep(rand() % 100);
    }
    return NULL;
}

int main(int argc, const char* argv[])
{
    // 初始化读写锁
    pthread_rwlock_init(&rwlock, NULL);

    // 创建5个读线程，3个写线程
    pthread_t p1[5], p2[3];
    for(int i = 0; i < 5; ++i)
    {
        pthread_create(&p1[i], NULL, readNum, NULL);
    }
    for(int i = 0; i < 3; ++i)
    {
        pthread_create(&p2[i], NULL, writeNum, NULL);
    }

    // 回收创建的线程
    for(int i = 0; i < 5; ++i)
    {
        pthread_join(p1[i], NULL);
    }
    for(int i = 0; i < 3; ++i)
    {
        pthread_join(p2[i], NULL);
    }

    // 销毁读写锁
    pthread_rwlock_destroy(&rwlock);

    return 0;
}